namespace strategy {
  /**
   *
   * 策略模式 包括两部分
   * 第一部分是策略类 策略类封装了具体实现的算法,并负责计算过程
   * 第二部分是环境类 接受请求,然后把请求委托给某一个策略类 因此环境类还要储存某个策略以实现委托
   *
   * 缺点：必须知道所有策略类，并自行决定使用哪一个策略类
   *
   *  使用策略模式计算奖金 --- JavaScript设计模式与开发实践
   *  绩效为 S 的人年终奖有 4 倍工资，绩效为 A 的人年终奖有 3 倍工资，而绩效为 B 的人年终奖是 2 倍工资
   *
   *
   */

  // 环境类
  // 奖金类
  class Bonus {
    private salary?: number;
    private performance?: Performance;
    // 设置工资/绩效
    public setSalaryAndPerformance(salary: number, performance: Performance) {
      this.salary = salary;
      this.performance = performance;
    }
    // 获取计算结果
    public getBonus(): number {
      return this?.performance?.calculate(this.salary || 0) || 0;
    }
  }

  // 策略类

  // 绩效抽象类
  interface PerformanceType {
    calculate(salary: number): number;
  }
  abstract class Performance implements PerformanceType {
    public calculate(salary: number) {
      return salary;
    }
  }
  // S类
  class PerformanceS extends Performance {
    public calculate(salary: number) {
      return salary * 4;
    }
  }
  // A类
  class PerformanceA extends Performance {
    public calculate(salary: number) {
      return salary * 3;
    }
  }
  // B类
  class PerformanceB extends Performance {
    public calculate(salary: number) {
      return salary * 2;
    }
  }

  const bonus = new Bonus();
  bonus.setSalaryAndPerformance(1000, new PerformanceS());
  const res = bonus.getBonus();
  console.log(res);
}
